package com.dao;

import com.utils.JdbcUtils;


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 为了复用代码，所以设置为抽象类
 */
public abstract class BaseDao {
    //使用DBUtils操作数据库
  //  private QueryRunner queryRunner = new QueryRunner();

//    /**
//     * update()方法用来执行：Insert/Update/Detele语句
//     * @param sql
//     * @param args
//     * @return 如果返回-1说明执行失败，返回其他表示影响的行数
//     */
//    public int update(String sql, Object... args){
//        Connection connection = null;
//        PreparedStatement st = null;
//
//
//        try {
//            connection = JdbcUtils.getConnection();//获取连接
//            st = connection.prepareStatement(sql);//预编译
//            // 填充占位符
//            if (args != null && args.length > 0) {
//                for (int i = 0; i < args.length; i++) {
//                    st.setObject((i + 1), args[i]);
//                }
//            }
//
//            int i = st.executeUpdate();//执行
//            // System.out.println(i);
//            return i;//返回影响的条数
//        }catch (Exception e) {
//            e.printStackTrace();
//            throw new RuntimeException(e);
//        }
//
//
////        catch (SQLException e) {
////            e.printStackTrace();
////        }finally {
////            JdbcUtils.release(connection,st,null);
////        }
//
//
//
//        //  return -1;
//
//    }
//    /**
//     * 查询返回一个 javaBean 的 sql 语句
//     *
//     * @param type 返回的对象类型
//     * @param sql  执行的 sql 语句
//     * @param args sql 对应的参数值
//     * @param <T>  返回的类型的泛型
//     * @return
//     */
//    public <T> T queryForOne(Class<T> type, String sql, Object... args) {
//        Connection con = null;
//        try {
//            con = JdbcUtils.getConnection();
//
//            List<T> queryResult = query(type, con, sql, args);
//            if(queryResult != null &&queryResult.size()!=0){
//                //获取集合中的第一个元素
//                return queryResult.get(0);
//            }
//
//        }catch (Exception e) {
//            e.printStackTrace();
//            throw new RuntimeException(e);
//        }
//
//
////        catch (SQLException e) {
////            e.printStackTrace();
////        } finally {
////            JdbcUtils.release(con, null, null);
////        }
//        return null;
//    }
//
////
////
////    public <T> T query1(Class<T> cls,Connection connection, String sql, Object... args){
////        Object object = null;
////        PreparedStatement st = null;
////        ResultSet rs = null;
////        try {
////
////            st = connection.prepareStatement(sql);//预编译
////            // 填充占位符
////            for (int i = 0; i < args.length; i++) {
////                st.setObject((i + 1), args[i]);
////            }
////            rs=st.executeQuery();//执行
////            // 判断并分析结果集
////            if (rs.next()) {
////                object = rs.getObject(1);
////            }
////
////        } catch (SQLException e) {
////            e.printStackTrace();
////        }
////        return (T)object;
////    }
//
//
//    public <T> List<T> query(Class<T> cls,Connection connection, String sql, Object... args){
//        List list = new ArrayList();
//        PreparedStatement st=null;
//        ResultSet rs=null;
//
//
//        try {
//            st = connection.prepareStatement(sql);//预编译
//            // 填充占位符
//            for (int i = 0; i < args.length; i++) {
//                st.setObject((i + 1), args[i]);
//            }
//            rs=st.executeQuery();//执行
//
//            // 得到结果集的元数据对象（查询到的字段数量以及查询了哪些字段）
//            ResultSetMetaData resultSetMetaData = rs.getMetaData();
//
//            // 得到查询的字段数量
//            int fieldNum  = resultSetMetaData.getColumnCount();
//            // 判断并分析结果集
//            while (rs.next()) {
//                // 实例化对象
//                Object object = cls.newInstance();
//                // 遍历查询的字段数量，得到数据库中查询的每一个列名
//                for (int i = 1; i <= fieldNum; i++) {
//                    // getColumnLabel()：获取列名或别名
//                    //不用getColumnName()：为了避免多数据库适配出现错误
//                    String columnName = resultSetMetaData.getColumnLabel(i);
//                    // 通过反射，使用列名得到对应的field对象
//                    Field field = cls.getDeclaredField(columnName);
//                    // 拼接set方法，得到字符串
//                    //set方法后面对应的列名第一个单词要大写，其余小写
//                    String setMethod = "set" + columnName.substring(0,1).toUpperCase() + columnName.substring(1);
//                    // 通过反射，将set方法字符串反射成类中对应的set方法
//                    Method method = cls.getDeclaredMethod(setMethod, field.getType());
//                    // 得到查询的每一个字段对应的值
//                    Object value = rs.getObject(columnName);
//                    // 通过invoke方法调用set方法
//                    method.invoke(object, value);
////                    // 将Javabean设置到集合中
////                    list.add(object);
//
//                }
//                // 将Javabean设置到集合中
//                list.add(object);
//
//            }
//
//            return list;
//
//
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new RuntimeException(e);
//        }
//
//
////        catch (Exception e) {
////            e.printStackTrace();
////        }finally{
////            JdbcUtils.release(connection,st,null);
////        }
//        //return null;
//    }
//
//
//
//
//    /**
//     * 查询返回多个 javaBean 的 sql 语句
//     *
//     * @param type 返回的对象类型
//     * @param sql  执行的 sql 语句
//     * @param args sql 对应的参数值
//     * @param <T>  返回的类型的泛型
//     * @return
//     */
//    public <T> List<T> queryForList(Class<T> type, String sql, Object... args) {
//        Connection con = null;
//        try {
//            con = JdbcUtils.getConnection();
//            return query(type,con, sql, args);
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new RuntimeException(e);
//        }
//
//
//
////        catch (SQLException e) {
////            e.printStackTrace();
////        } finally {
////            JdbcUtils.release(con, null, null);
////        }
//        //return null;
//    }
//
//    /**
//     * 查询返回单个值的情况(执行返回一行一列的 sql 语句)
//     *
//     * @param sql  执行的 sql 语句
//     * @param args sql 对应的参数值
//     * @return
//     */
////    public Object queryForSingleValue(String sql, Object... args) {
////        Connection con = null;
////        try {
////            con = JdbcUtils.getConnection();
////            // ScalarHandler：将结果集中某一条记录的其中某一列的数据存成Object。
////            return queryRunner.query(con, sql, new ScalarHandler(), args);
////        } catch (SQLException e) {
////            e.printStackTrace();
////        } finally {
////            JdbcUtils.release(con, null, null);
////        }
////        return null;
////    }
//
//
//
//
//    public Object queryForSingleValue(String sql, Object... args) {
//        Object object = null;
//        Connection con= null;
//        PreparedStatement st= null;
//        ResultSet rs = null;
//
//        try {
//            // 获取数据库连接
//            con = JdbcUtils.getConnection();
//            // 预编译
//            st = con.prepareStatement(sql);
//            // 如果有参数，则设置参数，下标从1开始
//            if (args != null && args.length > 0) {
//                // 循环设置参数，设置参数类型为Object
//                for (int i = 0; i < args.length; i++){
//                    st.setObject(i+1, args[i]);
//                }
//            }
//            // 执行查询，返回结果集
//            rs = st.executeQuery();
//            // 判断并分析结果集
//            if (rs.next()) {
//                object = rs.getObject(1);
//            }
//
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new RuntimeException(e);
//        }
//
////        catch (Exception e) {
////            e.printStackTrace();
////        } finally {
////            // 关闭资源
////           JdbcUtils.release(con, st,rs );
////        }
//
//        return object;
//
//    }






    /**
     * update()方法用来执行：Insert/Update/Detele语句
     * @param sql
     * @param args
     * @return 如果返回-1说明执行失败，返回其他表示影响的行数
     */
    public int update(String sql, Object... args){
        Connection connection = null;
        PreparedStatement st = null;
        try {
            connection = JdbcUtils.getConnection();//获取连接
            st = connection.prepareStatement(sql);//预编译
            // 填充占位符
            for (int i = 0; i < args.length; i++) {
                st.setObject((i + 1), args[i]);
            }


            int i = st.executeUpdate();//执行
            // System.out.println(i);
            return i;//返回影响的条数
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }
    /**
     * 查询返回一个 javaBean 的 sql 语句
     *
     * @param type 返回的对象类型
     * @param sql  执行的 sql 语句
     * @param args sql 对应的参数值
     * @param <T>  返回的类型的泛型
     * @return
     */
    public <T> T queryForOne(Class<T> type, String sql, Object... args) {
        Connection con = null;
        try {
            con = JdbcUtils.getConnection();

            List<T> queryResult = query(type, con, sql, args);
            if(queryResult != null &&queryResult.size()!=0){
                //获取集合中的第一个元素
                return queryResult.get(0);
            }
            return null;
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }

//
//
//    public <T> T query1(Class<T> cls,Connection connection, String sql, Object... args){
//        Object object = null;
//        PreparedStatement st = null;
//        ResultSet rs = null;
//        try {
//
//            st = connection.prepareStatement(sql);//预编译
//            // 填充占位符
//            for (int i = 0; i < args.length; i++) {
//                st.setObject((i + 1), args[i]);
//            }
//            rs=st.executeQuery();//执行
//            // 判断并分析结果集
//            if (rs.next()) {
//                object = rs.getObject(1);
//            }
//
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }
//        return (T)object;
//    }


    public <T> List<T> query(Class<T> cls,Connection connection, String sql, Object... args){
        List list = new ArrayList();
        PreparedStatement st=null;
        ResultSet rs=null;


        try {
            st = connection.prepareStatement(sql);//预编译
            // 填充占位符
            for (int i = 0; i < args.length; i++) {
                st.setObject((i + 1), args[i]);
            }
            rs=st.executeQuery();//执行

            // 得到结果集的元数据对象（查询到的字段数量以及查询了哪些字段）
            ResultSetMetaData resultSetMetaData = rs.getMetaData();

            // 得到查询的字段数量
            int fieldNum  = resultSetMetaData.getColumnCount();
            // 判断并分析结果集
            while (rs.next()) {
                // 实例化对象
                Object object = cls.newInstance();
                // 遍历查询的字段数量，得到数据库中查询的每一个列名
                for (int i = 1; i <= fieldNum; i++) {
                    // getColumnLabel()：获取列名或别名
                    //不用getColumnName()：为了避免多数据库适配出现错误
                    String columnName = resultSetMetaData.getColumnLabel(i);
                    // 通过反射，使用列名得到对应的field对象
                    Field field = cls.getDeclaredField(columnName);
                    // 拼接set方法，得到字符串
                    //set方法后面对应的列名第一个单词要大写，其余小写
                    String setMethod = "set" + columnName.substring(0,1).toUpperCase() + columnName.substring(1);
                    // 通过反射，将set方法字符串反射成类中对应的set方法
                    Method method = cls.getDeclaredMethod(setMethod, field.getType());
                    // 得到查询的每一个字段对应的值
                    Object value = rs.getObject(columnName);
                    // 通过invoke方法调用set方法
                    method.invoke(object, value);
                }
                // 将Javabean设置到集合中
                list.add(object);

            }

            return list;



        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }




    /**
     * 查询返回多个 javaBean 的 sql 语句
     *
     * @param type 返回的对象类型
     * @param sql  执行的 sql 语句
     * @param args sql 对应的参数值
     * @param <T>  返回的类型的泛型
     * @return
     */
    public <T> List<T> queryForList(Class<T> type, String sql, Object... args) {
        Connection con = null;
        try {
            con = JdbcUtils.getConnection();
            return query(type,con, sql, args);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    /**
     * 查询返回单个值的情况(执行返回一行一列的 sql 语句)
     *
     * @param sql  执行的 sql 语句
     * @param args sql 对应的参数值
     * @return
     */
//    public Object queryForSingleValue(String sql, Object... args) {
//        Connection con = null;
//        try {
//            con = JdbcUtils.getConnection();
//            return null;
//                    //queryRunner.query(con, sql, new ScalarHandler(), args);
//        } catch (SQLException e) {
//            e.printStackTrace();
//        } finally {
//            JdbcUtils.release(con, null, null);
//        }
//        return null;
//    }


    public Object queryForSingleValue(String sql, Object... args) {
        Object object = null;
        Connection con= null;
        PreparedStatement st= null;
        ResultSet rs = null;

        try {
            // 获取数据库连接
            con = JdbcUtils.getConnection();
            // 预编译
            st = con.prepareStatement(sql);
            // 如果有参数，则设置参数，下标从1开始
            if (args != null && args.length > 0) {
                // 循环设置参数，设置参数类型为Object
                for (int i = 0; i < args.length; i++){
                    st.setObject(i+1, args[i]);
                }
            }
            // 执行查询，返回结果集
            rs = st.executeQuery();
            // 判断并分析结果集
            if (rs.next()) {
                object = rs.getObject(1);
            }
            return object;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }



    }
}




//
//import com.utils.JdbcUtils;
//
//
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.sql.*;
//import java.util.ArrayList;
//import java.util.List;
//
///**
// * 为了复用代码，所以设置为抽象类
// */
//public abstract class BaseDao {
//    //使用DBUtils操作数据库
//  //  private QueryRunner queryRunner = new QueryRunner();
//
//
//    /**
//     * update()方法用来执行：Insert/Update/Detele语句
//     * @param sql
//     * @param args
//     * @return 如果返回-1说明执行失败，返回其他表示影响的行数
//     */
//    public int update(String sql, Object... args){
//        Connection connection = null;
//        PreparedStatement st = null;
//
//
//        try {
//            connection = JdbcUtils.getConnection();//获取连接
//            st = connection.prepareStatement(sql);//预编译
//            // 填充占位符
//            for (int i = 0; i < args.length; i++) {
//                st.setObject((i + 1), args[i]);
//            }
//
//
//            int rows = st.executeUpdate();//执行
//           // System.out.println(i);
//            return rows;//返回影响的条数
//        } catch (Exception e) {
//            e.printStackTrace();
//        }finally {
//            JdbcUtils.release(connection,st,null);
//        }
//        return -1;
//
//    }
//    /**
//     * 查询返回一个 javaBean 的 sql 语句
//     *
//     * @param type 返回的对象类型
//     * @param sql  执行的 sql 语句
//     * @param args sql 对应的参数值
//     * @param <T>  返回的类型的泛型
//     * @return
//     */
////    public <T> T queryForOne(Class<T> type, String sql, Object... args) {
////        Connection con = null;
////        try {
////
////            con = JdbcUtils.getConnection();
////            List<T> queryResult = query(type, con, sql, args);
////            if(queryResult.size()!=0){
////                //获取集合中的第一个元素
////                return queryResult.get(0);
////            }
////        } catch (Exception e) {
////            e.printStackTrace();
////        } finally {
////            JdbcUtils.release(con, null, null);
////        }
////        return null;
////    }
//
//    public <T> T queryForOne(Class<T> type, String sql, Object... args) {
//        Connection con = null;
//        try {
//            con = JdbcUtils.getConnection();
//            //获取集合中的第一个元素
//            return query(type,con, sql, args).get(0);
//        } catch (SQLException e) {
//            e.printStackTrace();
//        } finally {
//            JdbcUtils.release(con, null, null);
//        }
//        return null;
//    }
//
//
//
//    public <T> List<T> query(Class<T> cls,Connection connection, String sql, Object... args){
//        List list = new ArrayList();
//        PreparedStatement st=null;
//        ResultSet rs=null;
//
//
//        try {
//            st = connection.prepareStatement(sql);//预编译
//            // 填充占位符
//            for (int i = 0; i < args.length; i++) {
//                st.setObject((i + 1), args[i]);
//            }
//            rs=st.executeQuery();//执行
//
//            // 得到结果集的元数据对象（查询到的字段数量以及查询了哪些字段）
//            ResultSetMetaData resultSetMetaData = rs.getMetaData();
//
//            // 得到查询的字段数量
//            int fieldNum  = resultSetMetaData.getColumnCount();
//            // 实例化对象
//            Object object = cls.newInstance();
//             // 判断并分析结果集
//            while (rs.next()) {
//                // 遍历查询的字段数量，得到数据库中查询的每一个列名
//                for (int i = 1; i <= fieldNum; i++) {
//                    // getColumnLabel()：获取列名或别名
//                    //不用getColumnName()：为了避免多数据库适配出现错误
//                    String columnName = resultSetMetaData.getColumnLabel(i);
//                    // 通过反射，使用列名得到对应的field对象
//                    Field field = cls.getDeclaredField(columnName);
//                    // 拼接set方法，得到字符串
//                    //set方法后面对应的列名第一个单词要大写，其余小写
//                    String setMethod = "set" + columnName.substring(0,1).toUpperCase() + columnName.substring(1);
//                    // 通过反射，将set方法字符串反射成类中对应的set方法
//                    Method method = cls.getDeclaredMethod(setMethod, field.getType());
//                    // 得到查询的每一个字段对应的值
//                    Object value = rs.getObject(columnName);
//                    // 通过invoke方法调用set方法
//                    method.invoke(object, value);
//                }
//                // 将Javabean设置到集合中
//                list.add(object);
//
//            }
//
//            return list;
//
//
//
//        } catch (Exception e) {
//            e.printStackTrace();
//        }finally{
//            JdbcUtils.release(connection,st,rs);
//        }
//        return null;
//    }
//
//
//
//
//    /**
//     * 查询返回多个 javaBean 的 sql 语句
//     *
//     * @param type 返回的对象类型
//     * @param sql  执行的 sql 语句
//     * @param args sql 对应的参数值
//     * @param <T>  返回的类型的泛型
//     * @return
//     */
//    public <T> List<T> queryForList(Class<T> type, String sql, Object... args) {
//        Connection con = null;
//        try {
//            con = JdbcUtils.getConnection();
//            return query(type,con, sql, args);
//        } catch (SQLException e) {
//            e.printStackTrace();
//        } finally {
//            JdbcUtils.release(con, null, null);
//        }
//        return null;
//    }
//
//    /**
//     * 查询返回单个值的情况(执行返回一行一列的 sql 语句)
//     *
//     * @param sql  执行的 sql 语句
//     * @param args sql 对应的参数值
//     * @return
//     */
//    public Object queryForSingleValue(String sql, Object... args) {
//        Connection con = null;
//        try {
//            con = JdbcUtils.getConnection();
//            return null;
//                //    queryRunner.query(con, sql, new ScalarHandler(), args);
//        } catch (SQLException e) {
//            e.printStackTrace();
//        } finally {
//            JdbcUtils.release(con, null, null);
//        }
//        return null;
//    }
//}
